package travelDream.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;

import travelDream.ejb.prodotto.base.EscursioneDTO;
import travelDream.ejb.prodotto.base.HotelDTO;
import travelDream.ejb.prodotto.base.ProdottoBase;
import travelDream.ejb.prodotto.base.TrasportoDTO;
import travelDream.ejb.prodotto.base.VoloDTO;
import travelDream.entities.Escursione;
import travelDream.entities.Hotel;
import travelDream.entities.Trasporto;
import travelDream.entities.Volo;

@Stateless
public class AggiornaProdottoBase implements ProdottoBase{
	
	@PersistenceContext
	private EntityManager em;

	@Resource
	private EJBContext context;

	
	/*
	 * ********************************
	 * (non-Javadoc)
	 * 	VOLI 
	 * ********************************
	 */
	public void nuovoVolo(VoloDTO voloDTO){
		Volo volo = new Volo(voloDTO);
		em.persist(volo);
	}
	public void modificaVolo(VoloDTO volo){
		em.merge(convertDTOtoE(volo));
	}
	public void cancellaVolo(VoloDTO voloDTO){
		Volo volo = em.merge(convertDTOtoE(voloDTO));
		em.remove(volo);
	}
	
	private Volo convertDTOtoE(VoloDTO voloDTO){
		return new Volo(voloDTO);
	}
	private VoloDTO convertEtoDTO(Volo volo){
		return new VoloDTO(volo.getIdVolo(), volo.getDescrizione(), volo.getLuogoPartenza(), 
				volo.getLuogoArrivo(), volo.getOrarioPartenza(), volo.getOrarioArrivo(), volo.getCosto());
	}
	
	public List<VoloDTO> listaVolo(){
		List<VoloDTO> lista = new ArrayList<VoloDTO>();
		for(Volo v : listaVoliPrivate()){
			lista.add(convertEtoDTO(v));
		}
		return lista;
	}
	private List<Volo> listaVoliPrivate(){
		return em.createNamedQuery("Volo.findAll", Volo.class).getResultList();
	}
	
	public VoloDTO getVoloDTOById(int id){
		return convertEtoDTO(getVoloById(id));
	}

	private Volo getVoloById(int id){
		try{
			return em.createNamedQuery("Volo.findById", Volo.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException e){
			return null;
		}
	}
	
	
	
	
	
	
	/*
	 * ********************************
	 * (non-Javadoc)
	 * HOTEL
	 * ********************************
	 */
	
	
	/**
	 * Passando come parametro un HotelDTO crea un nuovo hotel nel database
	 */
	public void nuovoHotel(HotelDTO hotelDTO){
		Hotel hotel = new Hotel(hotelDTO);
		em.persist(hotel);
	}
	
	
	/**
	 * Passando come parametro un HotelDTO modifica l'hotel nel database
	 */
	public void modificaHotel(HotelDTO hotel){
		em.merge(convertDTOtoE(hotel));
	}	
	
	
	/**
	 * Elimina dal database l'hotel passato tramite parametro
	 * @param hotel
	 */
	public void cancellaHotel(HotelDTO hotelDTO){
		Hotel hotel = em.merge(convertDTOtoE(hotelDTO));
		em.remove(hotel);
	}
	
	
	/**
	 * Restituisce la lista di tutti gli hotel (in formato HotelDTO) esistenti
	 */
	public List<HotelDTO> listaHotel(){
		List<HotelDTO> lista = new ArrayList<HotelDTO>();
		for(Hotel h : listaHotelPrivate()){
			lista.add(convertEtoDTO(h));
		}
		return lista;
	}
	
	
	/**
	 * Restituisce la lista di tutti gli hotel (in formato Hotel) esistenti
	 * @return
	 */
	private List<Hotel> listaHotelPrivate() {
		try{
			return em.createNamedQuery("Hotel.findAll", Hotel.class).getResultList();
		}
		catch(NoResultException e){
			return null;
		}
	}
	
	
	/**
	 * Passando come parametro un id viene restituito l'HotelDTO corrispondente
	 */
	public HotelDTO getHotelDTOById(int id){
		return convertEtoDTO(getHotelById(id));
	}
	
	
	/**
	 * Passando come parametro un id viene restituito l'Hotel corrispondente
	 */
	private Hotel getHotelById(int id){
		try{
			return em.createNamedQuery("Hotel.findById", Hotel.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException e){
			return null;
		}
	}
	
	
	/**
	 * Converto un Hotel in HotelDTO
	 */
	private HotelDTO convertEtoDTO(Hotel h){
		HotelDTO hotel = new HotelDTO(h.getIdHotel(),h.getNome(),h.getDescrizione(), 
				h.getContatti(), h.getIndirizzo(), h.getStelle(), h.getCosto(), h.getLuogo());
		return hotel;
	}
	
	
	/**
	 * Converte un HotelDTO in un Hotel
	 * @param h
	 * @return
	 */
	private Hotel convertDTOtoE(HotelDTO h){
		Hotel hotel = new Hotel(h);
		return hotel;
	}
	
	
	
	
	/*
	 * ********************************
	 * (non-Javadoc)
	 * ESCURSIONI
	 * ********************************
	 */
	
	public void nuovaEscursione(EscursioneDTO escursioneDTO){
		Escursione escursione = new Escursione(escursioneDTO);
		em.persist(escursione);
	}
	
	public void modificaEscursione(EscursioneDTO esc){
		em.merge(convertDTOtoE(esc));
	}	
	
	
	public void cancellaEscursione(EscursioneDTO escDTO){
		Escursione esc = em.merge(convertDTOtoE(escDTO));
		em.remove(esc);
	}
	
	public List<EscursioneDTO> listaEscursione(){
		List<EscursioneDTO> lista = new ArrayList<EscursioneDTO>();
		for(Escursione e : listaEscursionePrivate()){
			lista.add(convertEtoDTO(e));
		}
		return lista;
	}
	
	private List<Escursione> listaEscursionePrivate() {
		return em.createNamedQuery("Escursione.findAll", Escursione.class).getResultList();
	}
	
	@Override
	public EscursioneDTO getEscursioneDTOById(int id) {
		return convertEtoDTO(getEscursioneById(id));
	}
	
	private Escursione getEscursioneById(int id){
		try{
			return em.createNamedQuery("Escursione.findById", Escursione.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	}
	
	private EscursioneDTO convertEtoDTO(Escursione e){
		EscursioneDTO esc = new EscursioneDTO(e.getIdEscursione(),e.getNome(),e.getDescrizione(), 
				e.getLuogo(), e.getCosto());
		return esc;
	}
	
	private Escursione convertDTOtoE(EscursioneDTO e){
		Escursione esc = new Escursione(e);
		return esc;
	}
	
	
	/*
	 * TRASPORTO
	 * Non ci sono inserimenti,cancellazioni e modifiche sul database
	 * perch queste operazioni sono gestite a livello di TRIGGER mysql
	 * direttamente sul database al momento dell'inserimento/cancellazione
	 * di un trasporto (volo, auto, traghetto, ecc)
	 */
	
	public TrasportoDTO getTrasportoDTOByIdTrasporto(int idTrasporto){
		return convertEtoDTO(getTrasportoByidTrasporto(idTrasporto));
	}
	
	private Trasporto getTrasportoByidTrasporto(int idTrasporto){
		try{
			return em.createNamedQuery("Trasporto.findByIdTrasporto", Trasporto.class).setParameter("idTrasporto", idTrasporto).getSingleResult();
		}
		catch(NoResultException e){
			return null;
		}
	
	}
	
	public TrasportoDTO getTrasportoDTOByIdMezzo(int idMezzo){
		return convertEtoDTO(getTrasportoByIdMezzo(idMezzo));
	}
	
	public VoloDTO getVoloDTOByIdTrasporto(int idTrasporto){
		return convertEtoDTO(getVoloByIdTrasporto(idTrasporto));
	}
	
	public Volo getVoloByIdTrasporto(int idTrasporto){
		int idVolo = getTrasportoByidTrasporto(idTrasporto).getIdMezzo();
		return getVoloById(idVolo);
	}
	
	public Trasporto getTrasportoByIdMezzo(int idMezzo){
		try{
			return em.createNamedQuery("Trasporto.findVoloByIdMezzo", Trasporto.class).setParameter("idMezzo", idMezzo).getSingleResult();
		}
		catch(NoResultException e){
			return null;
		}
	}
	
	private Trasporto convertDTOtoE(TrasportoDTO trasportoDTO){
		return new Trasporto(trasportoDTO.getIdTrasporto(), trasportoDTO.getIdMezzo(), trasportoDTO.getTipologia());
	}
	
	private TrasportoDTO convertEtoDTO(Trasporto trasporto){
		TrasportoDTO trasportoDTO = new TrasportoDTO(trasporto.getIdTrasporto(), trasporto.getIdMezzo(), trasporto.getTipologia());
		trasportoDTO.setVolo(getVoloDTOById(trasportoDTO.getIdMezzo()));
		return trasportoDTO;
	}
	

	
}
